<?php
/**
 * Created by PhpStorm.
 * User: DELL-PC
 * Date: 2018/8/8
 * Time: 11:05
 */

namespace J\Schema\Collection\Element;


use J\Schema\IElement;
use J\Schema\Collection\ICollection;
use J\Schema\Sprite;
use J\Schema\Syntax;
use J\ReadOnly;
use J\Util\ValidEvent;

class Element implements IElement
{
    /**
     * @var string
     */
    protected $name;

    /**
     * @var ReadOnly
     */
    protected $config;

    /**
     * @var ICollection
     */
    protected $collection;

    /**
     * @var ValidEvent
     */
    protected $validator = null;

    /**
     * @var Helper
     */
    protected $helper = null;

    /**
     * Element constructor.
     * @param string $name
     * @param array $config
     * @param ICollection $collection
     */
    public function __construct(string $name, array $config, ICollection $collection)
    {
        $this->name = strtolower($name);
        $this->config = new ReadOnly($config);
        $this->collection = $collection;
    }


    public function getAttribute()
    {
        return $this->config;
    }

    public function getName()
    {
        return $this->name;
    }

    public function getLabel()
    {
        return $this->getAttribute()->get('label', $this->getName());
    }

    public function getColumnName()
    {
        return $this->getAttribute()->get('column', $this->getName());
    }

    public function getColumnType()
    {
        return $this->getAttribute()->get('type') & Syntax::MASK_VALUE;
    }

    public function getFieldName()
    {
        return $this->getAttribute()->get('field', $this->getName());
    }

    public function getFieldType()
    {
        return $this->getAttribute()->get('holder',
            $this->getOperatorHelper()->getFieldType());
    }

    public function isBelongs()
    {
        return false;
    }

    public function getCollection()
    {
        return $this->collection;
    }

    public function getSprite($value, $operator = null, $default = null, $raw = false)
    {
        return new Sprite(
            $this,
            $value,
            $operator
        );
    }

    public function canNull()
    {
        return !($this->getAttribute()->get('type') & Syntax::MASK_NOT_NULL);
    }

    public function hasDefault()
    {
        return $this->getAttribute()->has('default');
    }

    public function getDefault()
    {
        return $this->getAttribute()->get('default');
    }

    public function must()
    {
        return $this->getAttribute()->get('type') & Syntax::MASK_MUST;
    }

    protected function isUnique()
    {
        return $this->getAttribute()->get('type') & Syntax::MASK_UNIQUE;
    }

    public function unique($value)
    {
        return !$this->isUnique() Or $this->collection->unique($this->name, $value);
    }

    public function valid($value)
    {
        if($this->validator){
            return false !== $this->validator->fire($value);
        }
        return true;
    }

    protected function prepare()
    {
        $this->setValidator($this->getAttribute()->get('valid'));
    }

    protected function setValidator($validator)
    {
        if (is_array($validator)){
            $this->validator = new ValidEvent();
            $this->validator->binding($validator);
        }
    }

    public function getOptions($where = true)
    {
        $options = $this->getAttribute()->get('options', []);
        $r = [];
        foreach ($options as $k => $v) {
            $r[$k] = [
                'value' => $k,
                'label' => $v,
            ];
        }
        return $r;
    }

    public function getOperatorHelper()
    {
        if(!$this->helper){
            $this->helper = Helper::factory($this);
        }
        return $this->helper;
    }

    public function fillValue(&$rs, $raw = false)
    {
        $column = $this->getColumnName();

        foreach ($rs as &$record) {
            // if ($this->name === $column) continue;
            $record[$this->name] = $this->display($record[$column]);
        }
    }

    protected function display($value)
    {
        $func = $this->getAttribute()->get('display');
        if ($func) return $func($value);

        $this->getOperatorHelper()->display($value);
        return $value;
    }

    public function getInputValue($default = null)
    {
        return array_isset($_REQUEST, $this->getFieldName(), $default);
    }
}